package com.copa.gamestore.module.order.application.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.copa.gamestore.common.enums.RefundStatus;
import com.copa.gamestore.common.response.ResponseVo;
import com.copa.gamestore.module.cart.application.CartApplicationService;
import com.copa.gamestore.module.cart.vo.CartGoodsVo;
import com.copa.gamestore.module.cart.vo.CartVo;
import com.copa.gamestore.module.gameGoods.application.GameGoodsApplicationService;
import com.copa.gamestore.module.order.application.OrderApplicationService;
import com.copa.gamestore.module.order.domain.Order;
import com.copa.gamestore.module.order.domain.OrderDetail;
import com.copa.gamestore.module.order.domain.OrderLog;
import com.copa.gamestore.module.order.dto.OrderDto;
import com.copa.gamestore.module.order.mapper.OrderDetailMapper;
import com.copa.gamestore.module.order.mapper.OrderMapper;
import com.copa.gamestore.module.order.service.OrderDetailService;
import com.copa.gamestore.module.order.service.OrderLogService;
import com.copa.gamestore.module.order.service.OrderService;
import com.copa.gamestore.module.order.vo.OrderAdminListVo;
import com.copa.gamestore.module.order.vo.OrderLogVo;
import com.copa.gamestore.module.order.vo.OrderVo;
import com.copa.gamestore.module.user.application.UserApplicationService;
import com.copa.gamestore.module.user.domain.User;
import com.copa.gamestore.module.user.domain.UserAccount;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author copa
 * @createDate 2022-09-27 17:57
 * @function
 */
@Service
public class OrderApplicationServiceImpl implements OrderApplicationService {

    @Resource
    private CartApplicationService cartApplicationService;

    @Resource
    private OrderService orderService;

    @Resource
    private OrderDetailService orderDetailService;

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private GameGoodsApplicationService gameGoodsApplicationService;

    @Resource
    private UserApplicationService userApplicationService;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderLogService orderLogService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<OrderVo> order(OrderDto orderDto) {
        cartApplicationService.validateUser(orderDto.getCartIds());
        CartVo cartVo = cartApplicationService.get().getData();
        if (Objects.isNull(cartVo.getCartGoodsVo()) || cartVo.getCartGoodsVo().size() <= 0) {
            return ResponseVo.successMsg("没有订单信息~");
        }
        Order order = orderService.add(cartVo, orderDto);
        List<OrderDetail> orderDetailList = orderDetailService.add(cartVo, order);
        List<Long> cartIds = cartVo.getCartGoodsVo().stream().map(CartGoodsVo::getId).collect(Collectors.toList());
        cartApplicationService.deleteByOrder(cartIds);
        // 加入日志
        add(new OrderLogVo().setOrderSn(order.getOrderSn())
                .setMoney(new BigDecimal(0))
                .setMessage("订单编号["+ order.getOrderSn() +"]已下单待支付"));
        return ResponseVo.success(
                new OrderVo().setOrder(order)
                        .setOrderDetail(orderDetailList)
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> finishPay(String orderSn) {
        BigDecimal money = orderService.finishPay(orderSn);
        // 加入日志
        add(new OrderLogVo().setOrderSn(orderSn)
                .setMoney(money)
                .setMessage("订单编号["+ orderSn +"]已支付，待收货"));
        userApplicationService.takeAccount(money, null);

        return ResponseVo.successMsg("支付成功~");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> cancelPay(String orderSn) {
        orderService.cancelPay(orderSn);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_sn", orderSn));
        orderDetailList.forEach(orderDetail -> gameGoodsApplicationService.stock(orderDetail.getGameGoodsId(), -orderDetail.getNum()));
        // 加入日志
        add(new OrderLogVo().setOrderSn(orderSn)
                .setMoney(new BigDecimal(0))
                .setMessage("订单编号["+ orderSn +"]已取消"));
        return ResponseVo.successMsg("取消订单成功~");
    }

    @Override
    public ResponseVo<List<Order>> list(Integer status) {
        User user = userApplicationService.userInfo();
        QueryWrapper<Order> wrapper = new QueryWrapper<Order>().eq("user_id", user.getId());
        if (Objects.nonNull(status)) {
            wrapper.eq("status", status);
        }
        return ResponseVo.success(orderMapper.selectList(wrapper));
    }

    @Override
    public ResponseVo<OrderVo> get(String orderSn) {
        User user = userApplicationService.userInfo();
        Order order = orderMapper.selectOne(new QueryWrapper<Order>()
                .eq("user_id", user.getId())
                .eq("order_sn", orderSn));
        List<OrderDetail> orderDetailList = null;
        if (Objects.nonNull(order)) {
            orderDetailList = orderDetailMapper
                    .selectList(new QueryWrapper<OrderDetail>().eq("order_sn", order.getOrderSn()));
        }

        return ResponseVo.success(new OrderVo().setOrder(order).setOrderDetail(orderDetailList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> receive(String orderSn) {
        orderService.receive(orderSn);
        // 加入日志
        add(new OrderLogVo().setOrderSn(orderSn)
                .setMoney(new BigDecimal(0))
                .setMessage("订单编号["+ orderSn +"]已确认收货"));
        return ResponseVo.success("确认已收货成功~");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> refund(String orderSubSn) {
        orderDetailService.refund(orderSubSn);
        // 加入日志
        String orderSn = orderSubSn.substring(0, orderSubSn.indexOf("-"));
        add(new OrderLogVo().setOrderSn(orderSn)
                .setMoney(new BigDecimal(0))
                .setMessage("订单编号["+ orderSn +"]中的[" + orderSubSn + "]已发起退款申请，待审核"));
        return ResponseVo.success("发出退款申请成功~");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseVo<String> checkRefund(String orderSubSn, Integer refundStatus) {
        BigDecimal money = orderDetailService.checkRefund(orderSubSn, refundStatus);
        String orderSn = orderSubSn.substring(0, orderSubSn.indexOf("-"));
        UserAccount userAccount = userApplicationService.accountByUserId(orderMapper.selectOne(new QueryWrapper<Order>().eq("order_sn", orderSn)).getUserId());
        if (money.compareTo(new BigDecimal(-1)) > 0) {
            // 加入日志
            add(new OrderLogVo().setOrderSn(orderSn)
                    .setUserId(userAccount.getUserId())
                    .setMoney(money.negate())
                    .setMessage("订单编号["+ orderSn +"]中的[" + orderSubSn + "]退款成功"));
            userApplicationService.takeAccount(money.negate(), userAccount);
            return ResponseVo.success("处理成功~");
        }
        // 加入日志
        add(new OrderLogVo().setOrderSn(orderSn)
                .setUserId(userAccount.getUserId())
                .setMoney(new BigDecimal(0))
                .setMessage("订单编号["+ orderSn +"]中的[" + orderSubSn + "]退款申请不通过"));
        return ResponseVo.success("处理成功~");
    }

    @Override
    public ResponseVo<List<OrderAdminListVo>> checkRefundList() {
        return ResponseVo.success(orderService.listByStatus(null, RefundStatus.REFUNDING.getStatus()));
    }

    @Override
    public ResponseVo<List<OrderAdminListVo>> listAdmin(Integer status) {
        return ResponseVo.success(orderService.listByStatus(status, null));
    }

    @Override
    public ResponseVo<OrderVo> getAdmin(String orderSn) {
        Order order = orderMapper.selectOne(new QueryWrapper<Order>()
                .eq("order_sn", orderSn));
        List<OrderDetail> orderDetailList = null;
        if (Objects.nonNull(order)) {
            orderDetailList = orderDetailMapper
                    .selectList(new QueryWrapper<OrderDetail>().eq("order_sn", order.getOrderSn()));
        }
        ResponseVo<User> user = userApplicationService.getUser(order.getUserId());
        return ResponseVo.success(new OrderVo()
                .setOrder(order)
                .setOrderDetail(orderDetailList)
                .setNickname(user.getData().getRealName()));
    }

    @Override
    public ResponseVo<List<OrderLog>> getLog(String orderSn) {
        Long userId = userApplicationService.userInfo().getId();
        return ResponseVo.success(orderLogService.get(userId, orderSn));
    }

    @Override
    public ResponseVo<List<OrderLog>> getLogAdmin(String orderSn) {
        return ResponseVo.success(orderLogService.get(null, orderSn));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void timeOutOrderCheck() {

        orderService.timeOutOrderCheck();
    }

    @Override
    public void add(OrderLogVo orderLogVo) {
        orderLogService.add(orderLogVo);
    }
}
